﻿using System.Collections.Generic;
using System.Reflection;
using feather.attr;
using Newtonsoft.Json.Linq;

namespace feather.core
{
    /// <summary>
    /// 通过反射机制，包装对象的带有ActionMethod属性的方法为Action单元对象
    /// </summary>
    public class ActionUnitMethod : ActionUnit
    {
        /// <summary>
        /// 执行的对象
        /// </summary>
        private object obj;

        /// <summary>
        /// 执行的方法
        /// </summary>
        private MethodInfo method;

        /// <summary>
        /// Action控制器
        /// </summary>
        private ActionController actionController;

        public ActionUnitMethod(object obj, MethodInfo method, ActionController actionController)
        {
            this.obj = obj;
            this.method = method;
            this.actionController = actionController;
        }

        /// <summary>
        /// 取出方法参数，执行方法
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <returns></returns>
        public object Execute(object input)
        {
            ParameterInfo[] paramInfos = method.GetParameters();

            object[] args = new object[paramInfos.Length];

            if (input is IDictionary<string, object>)
            {
                IDictionary<string, object> inputMap = input as IDictionary<string, object>;

                for (int i = 0; i < paramInfos.Length; i++)
                {
                    ParameterInfo pi = paramInfos[i];

                    if (pi.ParameterType == typeof(ActionController))
                    {
                        args[i] = actionController;
                    }
                    else
                    {
                        InputParam[] ip = pi.GetCustomAttributes(typeof(InputParam), false) as InputParam[];

                        string paramName = pi.Name;
                        if (ip.Length > 0)
                            paramName = ip[0].Name;
                        inputMap.TryGetValue(paramName, out args[i]);
                    }
                }
            }
            else if(input is JObject)
            {
                JObject inputJson = input as JObject;

                for (int i = 0; i < paramInfos.Length; i++)
                {
                    ParameterInfo pi = paramInfos[i];

                    if (pi.ParameterType == typeof(ActionController))
                    {
                        args[i] = actionController;
                    }
                    else
                    {
                        InputParam[] ip = pi.GetCustomAttributes(typeof(InputParam), false) as InputParam[];

                        string paramName = pi.Name;
                        if (ip.Length > 0)
                            paramName = ip[0].Name;
                        args[i] = inputJson.GetValue(paramName);
                    }
                }
            }

            return method.Invoke(obj, args);
        }

    }
}
